package com.kehutong.work.order.manage.service;

import com.kehutong.common.DoveClient;
import com.kehutong.common.util.Token;
import com.kehutong.work.order.manage.entity.WorkOrderManage;
import com.kehutong.work.order.manage.entity.WorkOrderManageRecord;
import com.kehutong.work.order.manage.entity.WorkOrderManageReminders;
import com.kehutong.work.order.manage.entity.WorkOrderManageType;
import com.kehutong.work.order.manage.enums.DoorToDoorEnum;
import com.kehutong.work.order.manage.enums.EmergencyStateEnum;
import com.kehutong.work.order.manage.enums.WorkOrderHandleStateEnum;
import com.kehutong.work.order.manage.enums.WorkOrderStateEnum;
import org.coraframework.bean.Beans;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.orm.util.Enums;
import org.coraframework.util.IDGenerate;
import org.coraframework.util.Objects;
import org.coraframework.util.time.TimeUtil;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@WebService("/work/order/manage/service/api")
public class WorkOrderManageServiceAPI {

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    private DoveClient doveClient;
    @ReqMapping("/listPage")
    public Page<WorkOrderManage> listPage(JSONObject jsonObject) {
        FindPage<WorkOrderManage> findPage = jdbcSession.findPage(WorkOrderManage.class);

        // 提交时间
        String startCreateTime =jsonObject.getString("startCreateTime");
        String endCreateTime =jsonObject.getString("endCreateTime");
        if (Objects.nonEmpty(startCreateTime) && Objects.nonEmpty(endCreateTime)) {
            findPage.maxEq("createTime", startCreateTime);
            findPage.minEq("createTime", endCreateTime);
        }
        // 等待时长
        // 管理后台
        LocalDateTime now = LocalDateTime.now();
        Integer waitHour =jsonObject.getInteger("waitHour");
        if (Objects.nonNull(waitHour)) {
            if (waitHour > 7*24) {
                findPage.minEq("createTime", now.plusHours(-waitHour));
            } else {
                findPage.maxEq("createTime", now.plusHours(-waitHour));
            }
            // findPage.eq("workOrderState", WorkOrderStateEnum.ING);
        }
        // 企微端
        Integer startWaitHour =jsonObject.getInteger("startWaitHour");
        Integer endWaitHour =jsonObject.getInteger("endWaitHour");
        if (Objects.nonNull(startWaitHour) && Objects.nonNull(endWaitHour)) {
            findPage.maxEq("createTime", now.plusHours(-endWaitHour))
                    .minEq("createTime", now.plusHours(-startWaitHour));
                    // .eq("workOrderState", WorkOrderStateEnum.ING);
        } else if (Objects.nonNull(startWaitHour)){
            findPage.maxEq("createTime", now.plusHours(-startWaitHour));
                    // .eq("workOrderState", WorkOrderStateEnum.ING);
        } else {
            // continue
        }
        // 处理时间
        String startHandleTime =jsonObject.getString("startHandleTime");
        String endHandleTime =jsonObject.getString("endHandleTime");
        if (Objects.nonEmpty(startHandleTime) && Objects.nonEmpty(endHandleTime)) {
            findPage.maxEq("finishTime", startHandleTime);
            findPage.minEq("finishTime", endHandleTime);
        }
        JSONArray departments = jsonObject.getJSONArray("departments");
        if (Objects.nonEmpty(departments)) {
            // 提交部门
            try {
                //  1.远程调用部门获取该部门下员工信息
                JSONObject result = doveClient.post("/basic/employee/service/list", http -> {
                    JSONObject body = new JSONObject();
                    body.put("department", departments);
                    body.put("pageNo", 1);
                    body.put("pageSize", 1000000);
                    http.setBody(body.toString());
                });
                JSONArray data = result.getJSONObject("data")
                                       .getJSONArray("list");
                //  2.查找
                findPage.markBegin();
                for (int i = 0; i < data.size(); i++) {
                    JSONObject employeeJson = (JSONObject) data.get(i);
                    JSONArray departJsonArray = employeeJson.getJSONArray("department");
                    if (Objects.isEmpty(departJsonArray)) {
                        continue;
                    }
                    for (int j = 0; j < departJsonArray.size(); j++) {
                        String depart = String.valueOf(departJsonArray.get(j));
                        findPage.like("createUserDepart", depart).or();
                    }
                }
                findPage.markEnd().and();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 提交人员
        JSONArray createUsers = jsonObject.getJSONArray("createUsers");
        if(Objects.nonEmpty(createUsers)) {
            findPage.markBegin();
            for (Object createUser : createUsers){
                findPage.like("createUserNo", createUser);
            }
            findPage.markEnd().and();
        }
        // 处理人员
        JSONArray handleUsers = jsonObject.getJSONArray("handleUsers");
        if(Objects.nonEmpty(handleUsers)) {
            findPage.markBegin();
            for (Object handleUser : handleUsers){
                findPage.like("handleEmployeeNo", handleUser);
            }
            findPage.markEnd().and();
        }

        JSONArray workOrderStateList = jsonObject.getJSONArray("workOrderStateList");
        if (Objects.nonEmpty(workOrderStateList)) {
            findPage.in("workOrderState", workOrderStateList);
        }

        String name = jsonObject.getString("name");
        if (Objects.nonEmpty(name)) {
            findPage.markBegin();
            findPage.like( "name", name).or();
            findPage.like("content", name).or();
            findPage.markEnd();
        }

        findPage.eq(jsonObject, "typeNo", "workOrderState", "emergency", "userAppraisal", "communityNo");
        findPage.eq("deleted", false);
        findPage.order("createTime", "desc");

        return findPage.page(jsonObject).exe();
    }

    public Page<WorkOrderManage> listAppPage(JSONObject jsonObject, String uuid) {
        FindPage<WorkOrderManage> findPage = jdbcSession.findPage(WorkOrderManage.class);

        // 1全部工单，2我发起的，3提交给我的，4抄送给我的
        int orderType = jsonObject.getIntValue("orderType");
        if (orderType == 1) {
            findPage.markBegin();
            findPage.eq("createUserNo", uuid).or();
            findPage.isNull("handleEmployeeNo").or();
            findPage.like("handleEmployeeNo", uuid).or();
            findPage.like("submitToMeNo", uuid).or();
            findPage.markEnd();
        } else if (orderType == 2) {
            findPage.eq("createUserNo", uuid);
        } else if (orderType == 3) {
            findPage.markBegin();
            findPage.isNull("handleEmployeeNo").or();
            findPage.like("submitToMeNo", uuid).or();
            findPage.markEnd();
        } else if (orderType == 4) {
            findPage.like("noticeEmployeeNo", uuid);
        } else {
            // continue
        }

        // 提交时间
        String startCreateTime =jsonObject.getString("startCreateTime");
        String endCreateTime =jsonObject.getString("endCreateTime");
        if (Objects.nonEmpty(startCreateTime) && Objects.nonEmpty(endCreateTime)) {
            findPage.maxEq("createTime", startCreateTime);
            findPage.minEq("createTime", endCreateTime);
        }
        // 等待时长
        LocalDateTime now = LocalDateTime.now();
        // 企微端
        Integer startWaitHour =jsonObject.getInteger("startWaitHour");
        Integer endWaitHour =jsonObject.getInteger("endWaitHour");
        if (Objects.nonNull(startWaitHour) && Objects.nonNull(endWaitHour)) {
            findPage.maxEq("createTime", now.plusHours(-endWaitHour))
                    .minEq("createTime", now.plusHours(-startWaitHour));
        } else if (Objects.nonNull(startWaitHour)){
            findPage.min("createTime", now.plusHours(-startWaitHour));
        } else {
            // continue
        }
        // 处理时间
        String startHandleTime =jsonObject.getString("startHandleTime");
        String endHandleTime =jsonObject.getString("endHandleTime");
        if (Objects.nonEmpty(startHandleTime) && Objects.nonEmpty(endHandleTime)) {
            findPage.maxEq("finishTime", startHandleTime);
            findPage.minEq("finishTime", endHandleTime);
        }

        // 处理人员
        JSONArray handleUsers = jsonObject.getJSONArray("handleUsers");
        if(Objects.nonEmpty(handleUsers)) {
            findPage.markBegin();
            for (Object handleUser : handleUsers){
                findPage.like("handleEmployeeNo", handleUser);
            }
            findPage.markEnd().and();
        }

        JSONArray workOrderStateList = jsonObject.getJSONArray("workOrderStateList");
        if (Objects.nonEmpty(workOrderStateList)) {
            findPage.in("workOrderState", workOrderStateList);
        }

        String name = jsonObject.getString("name");
        if (Objects.nonEmpty(name)) {
            findPage.markBegin();
            findPage.like( "name", name).or();
            findPage.like("content", name).or();
            findPage.markEnd();
        }

        findPage.eq(jsonObject, "typeNo", "workOrderState", "emergency", "communityNo");
        findPage.eq("deleted", false);
        findPage.order("createTime", "desc");

        Page<WorkOrderManage> page = findPage.page(jsonObject).exe();

        if (Objects.nonEmpty(page.getList())) {
            page.getList().forEach(e -> {
                e.setTokenUserCreate(uuid.equals(e.getCreateUserNo()));
                e.setTokenUserHandle(e.getHandleEmployeeNo().contains(uuid));
            });
        }

        return page;
    }

    public Object search(String uuid, JSONObject jsonObject){
        FindPage<WorkOrderManage> findPage = jdbcSession.findPage(WorkOrderManage.class);

        String name = jsonObject.getString("name");

        if (Objects.isEmpty(name)) {
            return Result.error(0, "请输入关键字");
        }
        if (Objects.nonEmpty(name)) {
            findPage.markBegin();
            findPage.like( "name", name).or();
            findPage.like("content", name).or();
            findPage.markEnd();
        }

        String searchType = jsonObject.getString("searchType");
        if (Objects.isEmpty(searchType)) {
            return Result.error(0, "请选择搜索类型");
        }
        if ("1".equals(searchType)) {
            findPage.like("submitToMeNo", uuid);
        } else if ("2".equals(searchType)) {
            findPage.like("createUserNo", uuid);
        } else if ("3".equals(searchType)) {
            findPage.like("noticeEmployeeNo", uuid);
        } else {
            // continue
            // Objects.isEmpty(searchType)
        }
        findPage.eq("deleted", false);

        return Result.success(findPage.page(jsonObject).exe());
    }

    public Object assign(Token token, JSONObject json, WorkOrderManage order) {
        if (checkFinalState(order.getWorkOrderState())) {
            return Result.error(0, "已达到最终状态，不允许继续操作");
        }
        try {
            // 设置必要权限
            setHandleEmployee(order, token.getUuid(), token.getUsername());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(0, "工单创建失败");
        }
        json.putAll(buildHandleUserJson(order, token.getUuid(), token.getUsername()));
        String recordId = insertRecord(json, order, WorkOrderHandleStateEnum.ASSIGN, true, false);
        order.setWorkOrderState(WorkOrderStateEnum.ING);
        order.setRecordId(recordId);
        jdbcSession.updateById(order);
        return Result.success();
    }

    public JSONObject getCommunityById(String id) throws Exception {
        JSONObject result = doveClient.post("/basic/community/service/get", http->{
            http.addParam("id", id);
        });

        JSONObject data = result.getJSONObject("data");

        if (Objects.isNull(data)) {
            return null;
        }

        return data;
    }
    @Bean(copy = true, newInstance = true)
    @ReqMapping("/save")
    public Object save(WorkOrderManage manage) {
        //JSONObject转实体
//        WorkOrderManage manage= Pool.newInstance(WorkOrderManage.class);
//        Beans.from(jsonObject).to(manage).copy();
        if (Objects.isEmpty(manage.getCommunityNo())
            || Objects.isEmpty(manage.getTypeNo())
            || Objects.isEmpty(manage.getOneClassifyNo())
            || Objects.isEmpty(manage.getContent())
            || Objects.isNull(manage.getEmergency())
            || Objects.isNull(manage.getDoorToDoor())
            || (!manage.isUserCreate() && Objects.isEmpty(manage.getHandleEmployeeNo()))
        ) {
            return Result.error(0, "请填写必填参数");
        }

        if (manage.isUserCreate() && Objects.isEmpty(manage.getBuildNo())) {
            return Result.error(0, "请先绑定房屋");
        }
        manage.setWorkOrderState(WorkOrderStateEnum.ING);
        if (manage.isUserCreate()){
            if (Objects.nonEmpty(manage.getBuildNo())){
                JSONObject buildJson = listEmployeeByHouseNo(manage.getBuildNo(), manage.getCompanyNo());
                if (Objects.isEmpty(manage.getCommunityNo())) {
                    manage.setCommunityNo(buildJson.getString("communityNo"));
                }
                JSONArray employeeNoArray = buildJson.getJSONArray("employeeNos");
                if (Objects.nonEmpty(employeeNoArray)){
                    List<String> employeeNos = JSONObject.parseArray(employeeNoArray.toJSONString(), String.class);
                    if (Objects.nonEmpty(employeeNos)) {
                        manage.setHandleEmployeeNo(employeeNos);
                    } else {
                        manage.setWorkOrderState(WorkOrderStateEnum.PRE_ASSIGNED);
                    }
                } else {
                    manage.setWorkOrderState(WorkOrderStateEnum.PRE_ASSIGNED);
                }
            }
        }else{
            JSONObject employeeJson = getEmployeeById(manage.getCreateUserNo());
            if (Objects.nonNull(employeeJson)) {
                if (Objects.nonEmpty(employeeJson.getJSONArray("department")))
                    manage.setCreateUserDepart(String.valueOf(employeeJson.getJSONArray("department").get(0)));
                if (Objects.nonEmpty(employeeJson.getJSONArray("departmentName")))
                    manage.setCreateUserDepartName(String.valueOf(employeeJson.getJSONArray("departmentName").get(0)));
            }
        }
        if (Objects.isEmpty(manage.getTypeName())) {
            WorkOrderManageType type = Pool.get(WorkOrderManageType.class, manage.getTypeNo());
            manage.setTypeName(type.getName());
        }
        if (Objects.nonEmpty(manage.getTwoClassifyName())) {
            manage.setName(manage.getTwoClassifyName());
        } else {
            manage.setName(manage.getOneClassifyName());
        }

        // 设置必要权限
       /* try {
            setHandleEmployee(manage, null, null);
            setDepart(manage);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(0, "工单创建失败");
        }
*/
        JSONObject json = buildHandleUserJson(manage, manage.getCreateUserNo(), manage.getCreateUserName());
        json.put("handlePositionTitle", manage.getHandlePositionTitle());
        json.put("avatar", manage.getAvatar());
        String recordId = insertRecord(json, manage, WorkOrderHandleStateEnum.CREATE, false, manage.isUserCreate());
        manage.setRecordId(recordId);

        int a = jdbcSession.insert(manage);

        if (Objects.nonEmpty(manage.getFileList())) {
            try {
                doveClient.post("/basic/annex/service/list/save", (http) -> {
                    JSONObject body = new JSONObject();
                    body.put("uuid", manage.getCreateUserNo());
                    body.put("username",manage.getCreateUserName());
                    body.put("fileList", manage.getFileList());
                    body.put("businessType", "1300");
                    body.put("businessId", manage.getId());
                    http.setBody(body.toJSONString());
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }



        return Result.success();
    }

    private void setDepart(WorkOrderManage manage) throws Exception {
        if (Objects.isEmpty(manage.getCommunityNo())) {
            return;
        }

        JSONObject communityJson = getCommunityById(manage.getCommunityNo());
        if (Objects.nonNull(communityJson)) {
            manage.setDepartmentNo(communityJson.getString("parent_id"));
            manage.setDepartmentName(communityJson.getString("parent_name"));
            JSONArray parentIdsArray = communityJson.getJSONArray("parent_ids");
            if (Objects.nonEmpty(parentIdsArray)) {
                manage.setDepartmentNos(JSONObject.parseArray(parentIdsArray.toJSONString(), String.class));
            }
        }
    }

    private JSONObject createNextEmployee(WorkOrderManage manage) {
        StringBuilder nextEmployeeNo = new StringBuilder();
        StringBuilder nextEmployeeName = new StringBuilder();
        for (int i = 0; i < manage.getHandleEmployeeNo().size(); i++) {
            if (i == manage.getHandleEmployeeNo().size() - 1) {
                nextEmployeeNo.append(manage.getHandleEmployeeNo().get(i));
            } else {
                nextEmployeeNo.append(manage.getHandleEmployeeNo().get(i)).append(",");
            }
        }
        for (int i = 0; i < manage.getHandleEmployeeName().size(); i++) {
            if (i == manage.getHandleEmployeeName().size() - 1) {
                nextEmployeeName.append(manage.getHandleEmployeeName().get(i));
            } else {
                nextEmployeeName.append(manage.getHandleEmployeeName().get(i)).append(",");
            }
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("nextUserNo", nextEmployeeNo.toString());
        jsonObject.put("nextUserName", nextEmployeeName.toString());
        return jsonObject;
    }

    /**
     * 通过id获取员工信息
     *
     * @param id
     * @return
     * @throws Exception
     */
    private JSONObject getEmployeeById(String id) {
        try {
            JSONObject object = doveClient.post("/basic/employee/service/get", (http) -> {
                JSONObject body = new JSONObject();
                body.put("id", id);

                http.setBody(body.toString());
            });
            if (object.getInteger("code") == 200) {
                return object.getJSONObject("data");
            } else {
                return null;
            }
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    private void setHandleEmployee(WorkOrderManage order, String uuid, String uuname) throws Exception {
        Set<String> handleEmployeeNameSet = new HashSet<>();
        Set<String> handleEmployeeDepartSet = new HashSet<>();
        Set<String> submitToMeSet = new HashSet<>(order.getSubmitToMeNo());
        Set<String> submitToMeNameSet = new HashSet<>(order.getSubmitToMeName());
        Set<String> authorityUserSet = new HashSet<>(order.getAuthorityUserList());

        if (Objects.nonEmpty(uuid)) {
            submitToMeSet.add(uuid);
            submitToMeNameSet.add(uuname);
            authorityUserSet.add(uuid);
        }

        JSONArray employeeJsonArray = remoteEmployeeList(order.getHandleEmployeeNo());
        for (int i = 0; i < employeeJsonArray.size(); i++) {
            JSONObject json = (JSONObject) employeeJsonArray.get(i);
            String employeeId = json.getString("id");
            String employeeName = json.getString("name");
            Set<String> departNameSet = json.getJSONArray("departmentName").stream().map(String::valueOf).collect(Collectors.toSet());
            handleEmployeeNameSet.add(employeeName);
            handleEmployeeDepartSet.addAll(departNameSet);
            submitToMeSet.add(employeeId);
            submitToMeNameSet.add(employeeName);
            authorityUserSet.add(employeeId);
        }

        order.setHandleEmployeeName(new ArrayList<>(handleEmployeeNameSet));
        order.setHandleDepartName(new ArrayList<>(handleEmployeeDepartSet));
        order.setSubmitToMeNo(new ArrayList<>(submitToMeSet));
        order.setSubmitToMeName(new ArrayList<>(submitToMeNameSet));
        order.setAuthorityUserList(new ArrayList<>(authorityUserSet));

    }

    private JSONArray remoteEmployeeList(List<String> employeeIds) throws Exception {
        if (Objects.isEmpty(employeeIds)) {
            return new JSONArray();
        }
        JSONObject result = doveClient.post("/basic/employee/service/list", http -> {
            JSONObject body = new JSONObject();
            body.put("id", employeeIds);
            body.put("pageNo", 1);
            body.put("pageSize", 1000000);
            http.setBody(body.toString());
        });

        return result.getJSONObject("data")
                               .getJSONArray("list");
    }

    private JSONObject listEmployeeByHouseNo(String houseNo, String companyNo) {
        try {
            JSONObject buildingResult = doveClient.post("/basic/building/service/get", (http) -> {
                Map<String, String> map =new HashMap<>();
                map.put("companyNo", companyNo);
                http.setHeaders(map);
                JSONObject body = new JSONObject();
                body.put("id", houseNo);
                http.setBody(body.toJSONString());
            });

            if (buildingResult.getIntValue("code")== 200) {
                JSONObject buildingJson=buildingResult.getJSONObject("data");
                if(Objects.nonNull(buildingJson)){
                    return buildingJson;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new JSONObject();
        }
        return new JSONObject();
    }

    @Bean(copy = true, newInstance = true)
    @ReqMapping("/delete")
    public Object delete(WorkOrderManage manage) {
        if (Objects.nonEmpty(manage.getCreateUserNo()) && Objects.nonNull(manage)) {
            synchronized (manage.getId().intern()) {
                List<String> authList = manage.getAuthorityUserList();
                authList.remove(manage.getCreateUserNo());
                manage.setAuthorityUserList(authList);
                jdbcSession.updateById(manage);
            }
        }

        return Result.success();
    }

    public Object detail(Token token, String id, boolean adminPage){
        WorkOrderManage order = Pool.get(WorkOrderManage.class, id);
        if (Objects.isNull(order)) {
            return Result.error(0, "工单不存在");
        }

        // if (!adminPage && !order.getAuthorityUserList().contains(token.getUuid())) {
        //     return Result.error(0, "您暂无权限查看此工单，工单ID：" + order.getId());
        // }

        List<WorkOrderManageRecord> recordList = jdbcSession.findArray(WorkOrderManageRecord.class)
                                                            .eq("workOrderId", id)
                                                            .order("createTime", "desc")
                                                            .exe();
        order.setRecordList(recordList);
        order.setReturnableEmployeeNo(order.getCreateUserNo());
        order.setReturnableEmployeeName(order.getCreateUserName());
        order.setTokenUserCreate(token.getUuid().equals(order.getCreateUserNo()));
        order.setTokenUserHandle(order.getHandleEmployeeNo().contains(token.getUuid()));

        return Result.success(order);
    }

    /**
     *
     * @param  ，含员工和用户
     * @param json
     * @return
     */
    @ReqMapping("/handleWorkOrder")
    public Object handleWorkOrder( JSONObject json){
        String id = json.getString("id");
        Boolean userCreate= Boolean.valueOf(json.getString("userCreate"));//是否用户发起的工单
        String uuid=json.getString("createUserNo");//提交人员ID 用户ID
        String uuName=json.getString("createUserName");//提交人员名字 用户名称
        WorkOrderManage order = Pool.get(WorkOrderManage.class, id);
        if (Objects.isNull(order)) {
            return Result.error(0, "工单不存在");
        }

        // if (!uuid.equals(order.getCreateUserNo()) && order.getWorkOrderState() != WorkOrderStateEnum.ING) {
        //     return Result.error(0, "不能操作该工单");
        // }

        WorkOrderHandleStateEnum type = Enums.getEnum(WorkOrderHandleStateEnum.class, json.getJSONObject("handleState").getString("id"));
        List<String> handleEmployeeNoList = new ArrayList<>();
        List<String> handleEmployeeNameList = new ArrayList<>();
        String recordId;
        switch (type) {
            case EDIT:
                editWorkOrder(json, order, userCreate);
                return Result.success();
            case REVOKE:
                if (checkFinalState(order.getWorkOrderState())) {
                    return Result.error(0, "已达到最终状态，不允许继续操作");
                }
                // 生成撤销工单记录
                json.putAll(buildHandleUserJson(order, uuid, uuName));
                recordId = insertRecord(json, order, WorkOrderHandleStateEnum.REVOKE, false, userCreate);
                // 设置终态
                order.setWorkOrderState(WorkOrderStateEnum.REVOKE);
                handleEmployeeNoList.add(uuid);
                handleEmployeeNameList.add(uuName);
                order.setHandleEmployeeNo(handleEmployeeNoList);
                order.setHandleEmployeeName(handleEmployeeNameList);
                order.setFinishTime(LocalDateTime.now());
                break;
            case REFUND:
                if (checkFinalState(order.getWorkOrderState())) {
                    return Result.error(0, "已达到最终状态，不允许继续操作");
                }
                order.setWorkOrderState(WorkOrderStateEnum.REFUND);
                handleEmployeeNoList.add(uuid);
                handleEmployeeNameList.add(uuName);
                order.setHandleEmployeeNo(handleEmployeeNoList);
                order.setHandleEmployeeName(handleEmployeeNameList);
                // 生成退回工单记录
                json.put("nextUserNo", order.getCreateUserNo());
                json.put("nextUserName", order.getCreateUserName());
                json.put("handleUserNo", uuid);
                json.put("handleUserName", Objects.nonEmpty(json.getString("createUserName")) ? json.getString("createUserName") : uuName);
                recordId = insertRecord(json, order, WorkOrderHandleStateEnum.REFUND, false, userCreate);
                order.setFinishTime(LocalDateTime.now());
                break;
            case SEND:
                if (checkFinalState(order.getWorkOrderState())) {
                    return Result.error(0, "已达到最终状态，不允许继续操作");
                }
                // 设置转他人状态
                order.setWorkOrderState(WorkOrderStateEnum.SEND);
                handleEmployeeNoList.add(json.getString("nextEmployeeNo"));
                order.setHandleEmployeeNo(handleEmployeeNoList);
                handleEmployeeNameList.add(json.getString("nextEmployeeName"));
                order.setHandleEmployeeName(handleEmployeeNameList);

                json.putAll(buildHandleUserJson(order, uuid, uuName));
                // 生成转他人记录
                recordId = insertRecord(json, order, WorkOrderHandleStateEnum.SEND, false, userCreate);
                break;
            case SUCCESS:
                if (checkFinalState(order.getWorkOrderState())) {
                    return Result.error(0, "已达到最终状态，不允许继续操作");
                }
                if (order.isSignIn()) {
                    WorkOrderManageRecord recordTemp = Pool.get(WorkOrderManageRecord.class, order.getRecordId());
                    if (recordTemp.getHandleState() != WorkOrderHandleStateEnum.SIGN_IN) {
                        return Result.error(0, "请先完成外勤签到");
                    }
                }
                handleEmployeeNoList.add(uuid);
                handleEmployeeNameList.add(uuName);
                order.setHandleEmployeeNo(handleEmployeeNoList);
                order.setHandleEmployeeName(handleEmployeeNameList);
                json.putAll(buildHandleUserJson(order, uuid, uuName));
                // 生成成功工单记录
                recordId = insertRecord(json, order, WorkOrderHandleStateEnum.SUCCESS, false, userCreate);
                order.setWorkOrderState(WorkOrderStateEnum.SUCCESS);
                order.setFinishTime(LocalDateTime.now());

                JSONArray jsonArray = json.getJSONArray("fileList");
                if (Objects.nonEmpty(jsonArray)) {
                    try {
                        doveClient.post("/basic/annex/service/list/save", (http) -> {
                            JSONObject body = new JSONObject();
                            body.put("uuid", uuid);
                            body.put("username", uuName);
                            body.put("fileList", jsonArray);
                            body.put("businessType", "1300");
                            body.put("businessId", order.getId());
                            http.setBody(body.toJSONString());
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                break;
            case SIGN_IN:
                if (checkFinalState(order.getWorkOrderState())) {
                    return Result.error(0, "已达到最终状态，不允许继续操作");
                }
                json.putAll(buildHandleUserJson(order, uuid, uuName));
                // 生成签到工单记录
                recordId = insertRecord(json, order, WorkOrderHandleStateEnum.SIGN_IN, true, userCreate);
                order.setSignInAddress(json.getString("address"));
                order.setSignInLng(json.getString("lng"));
                order.setSignInLat(json.getString("lat"));
                break;
            default:
                return Result.error(0, "请确认操作后，重试");
        }

        order.setRecordId(recordId);

        // 设置必要权限
    /*    try {
            if (!userCreate) {
                setHandleEmployee(order, uuid, uuName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(0, "操作失败");
        }
*/
        jdbcSession.updateById(order);
        return Result.success();
    }

    private boolean checkFinalState(WorkOrderStateEnum orderStateEnum) {

        if (orderStateEnum == WorkOrderStateEnum.REFUND || orderStateEnum == WorkOrderStateEnum.REVOKE || orderStateEnum == WorkOrderStateEnum.SUCCESS) {
            return true;
        }
        return false;
    }

    private void editWorkOrder(JSONObject json, WorkOrderManage order, boolean userCreate) {
        if (order.getWorkOrderState() == WorkOrderStateEnum.ING) {
            // 编辑当前工单
            setWorkOrder(json, order);
            try {
                setDepart(order);
            }catch (Exception e) {
                e.printStackTrace();
            }
            JSONObject jsonObject = buildHandleUserJson(order, order.getCreateUserNo(), order.getCreateUserName());
            json.putAll(jsonObject);

            // 生成编辑工单记录
            String recordId = insertRecord(json, order, WorkOrderHandleStateEnum.EDIT, true, userCreate);
            order.setRecordId(recordId);

            // 设置部门
            Set<String> departSet = new HashSet<>();
            for (int i = 0; i < order.getHandleEmployeeNo().size(); i++) {
                JSONObject employeeJson = getEmployeeById(order.getHandleEmployeeNo().get(i));
                if (Objects.nonNull(employeeJson)) {
                    JSONArray depart = employeeJson.getJSONArray("departmentName");
                    if (Objects.nonEmpty(depart)){
                        departSet.addAll(JSONArray.parseArray(depart.toJSONString(), String.class));
                    }
                }
            }
            order.setHandleDepartName(new ArrayList<>(departSet));

            jdbcSession.updateById(order);

            List<String> handleEmployee = order.getHandleEmployeeNo();
            if (Objects.nonEmpty(handleEmployee)) {
                handleEmployee.forEach(e -> notifyEmployee("1", e, order.getCreateUserNo(), order.getCreateUserName(), order.getName(), order.getId()));
            }
            List<String> noticeEmployee = order.getNoticeEmployeeNo();
            if (Objects.nonEmpty(noticeEmployee)) {
                noticeEmployee.forEach(e -> notifyEmployee("2", e, order.getCreateUserNo(), order.getCreateUserName(), order.getName(), order.getId()));
            }
        } else{
            // 重新生成工单
            WorkOrderManage tempOrder = order;
            initWorkOrder(tempOrder);
            tempOrder.setCreateUserNo(order.getCreateUserNo());
            tempOrder.setCreateUserName(order.getCreateUserName());
            tempOrder.setCreateUserDepartName(order.getCreateUserDepartName());
            // 重置找管家
            if (userCreate) {
                if (Objects.nonEmpty(tempOrder.getHouseNo())){
                    JSONObject buildJson = buildEmployee(tempOrder.getBuildNo(), json.getString("companyNo"));
                    if (Objects.nonEmpty(buildJson.getJSONArray("employeeNos")))
                        tempOrder.setHandleEmployeeNo(buildJson.getJSONArray("employeeNos").stream().map(String::valueOf).collect(Collectors.toList()));
                    if (Objects.nonEmpty(buildJson.getJSONArray("employeeNames")))
                        tempOrder.setHandleEmployeeName(buildJson.getJSONArray("employeeNames").stream().map(String::valueOf).collect(Collectors.toList()));
                    if (Objects.nonEmpty(buildJson.getJSONArray("departs")))
                        tempOrder.setHandleDepartName(buildJson.getJSONArray("departs").stream().map(String::valueOf).collect(Collectors.toList()));
                }
            }

            setWorkOrder(json, tempOrder);
            try {
                setDepart(tempOrder);
            }catch (Exception e) {
                e.printStackTrace();
            }

            JSONObject jsonObject = buildHandleUserJson(tempOrder, order.getCreateUserNo(), order.getCreateUserName());
            json.putAll(jsonObject);
            // 创建新的工单记录
            String recordId = insertRecord(json, tempOrder, WorkOrderHandleStateEnum.CREATE, false, userCreate);
            tempOrder.setRecordId(recordId);

            // 设置部门
            Set<String> departSet = new HashSet<>();
            for (int i = 0; i < order.getHandleEmployeeNo().size(); i++) {
                JSONObject employeeJson = getEmployeeById(order.getHandleEmployeeNo().get(i));
                if (Objects.nonNull(employeeJson)) {
                    JSONArray depart = employeeJson.getJSONArray("departmentName");
                    if (Objects.nonEmpty(depart)){
                        departSet.addAll(JSONArray.parseArray(depart.toJSONString(), String.class));
                    }
                }
            }
            order.setHandleDepartName(new ArrayList<>(departSet));

            jdbcSession.insert(tempOrder);

            List<String> handleEmployee = tempOrder.getHandleEmployeeNo();
            if (Objects.nonEmpty(handleEmployee)) {
                handleEmployee.forEach(e -> notifyEmployee("1", e, tempOrder.getCreateUserNo(), tempOrder.getCreateUserName(), tempOrder.getName(), tempOrder.getId()));
            }
            List<String> noticeEmployee = tempOrder.getNoticeEmployeeNo();
            if (Objects.nonEmpty(noticeEmployee)) {
                noticeEmployee.forEach(e -> notifyEmployee("2", e, tempOrder.getCreateUserNo(), tempOrder.getCreateUserName(), tempOrder.getName(), tempOrder.getId()));
            }
        }
    }

    private JSONObject buildEmployee(String houseNo, String companyNo) {
        JSONObject result = new JSONObject();
        try {
            JSONObject buildingResult = doveClient.post("/basic/building/service/get", (http) -> {
                Map<String, String> map =new HashMap<>();
                map.put("companyNo", companyNo);
                http.setHeaders(map);
                JSONObject body = new JSONObject();
                body.put("id", houseNo);
                http.setBody(body.toJSONString());
            });

            if (buildingResult.getIntValue("code")== 200) {
                JSONObject buildingJson=buildingResult.getJSONObject("data");
                if(Objects.nonNull(buildingJson)){
                    List<String> employeeNos = JSONObject.parseArray(buildingJson.getJSONArray("employeeNos").toJSONString(),String.class);
                    List<String> employeeNames = new ArrayList<>();
                    Set<String> departs = new HashSet<>();
                    if(Objects.nonEmpty(employeeNos)){
                        Set<String> employeeIds = new HashSet<>(employeeNos);
                        Map<String,JSONObject> employeeMap = getEmployeeMap(new ArrayList<>(employeeIds));
                        for (String employeeNo : employeeNos) {
                            JSONObject employee = employeeMap.get(employeeNo);
                            if(Objects.nonNull(employee)){
                                employeeNames.add(employee.getString("name"));
                                if (Objects.nonEmpty(employee.getJSONArray("departmentName")))
                                    departs.addAll(employee.getJSONArray("departmentName").stream().map(String::valueOf).collect(Collectors.toSet()));
                            }
                        }
                        result.put("employeeNos", employeeIds.toArray());
                        result.put("employeeNames", employeeNames);
                        result.put("departs", departs.toArray());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return result;
        }
    }

    public Map<String,JSONObject> getEmployeeMap(List<String> employeeIds) throws Exception {
        JSONObject result = doveClient.post("/basic/employee/service/list", http->{
            JSONObject body = new JSONObject();
            body.put("id", employeeIds);
            body.put("pageNo", 1);
            body.put("pageSize", 1000000);
            http.setBody(body.toString());
        });

        JSONArray data = result.getJSONObject("data").getJSONArray("list");

        if (Objects.isNull(data)) {
            return null;
        }

        Map<String,JSONObject> employeeMap = new HashMap<>();
        data.forEach(item->{
            JSONObject obj = (JSONObject) item;
            employeeMap.put(obj.getString("id"), obj);
        });

        return employeeMap;
    }

    private void setWorkOrder(JSONObject json, WorkOrderManage tempOrder) {
        tempOrder.setTypeNo(json.getString("typeNo"));
        if (Objects.isEmpty(json.getString("typeName"))) {
            WorkOrderManageType type = Pool.get(WorkOrderManageType.class, tempOrder.getTypeNo());
            tempOrder.setTypeName(type.getName());
        } else {
            tempOrder.setTypeName(json.getString("typeName"));
        }
        tempOrder.setOneClassifyNo(json.getString("oneClassifyNo"));
        tempOrder.setOneClassifyName(json.getString("oneClassifyName"));
        tempOrder.setTwoClassifyNo(json.getString("twoClassifyNo"));
        tempOrder.setTwoClassifyName(json.getString("twoClassifyName"));
        tempOrder.setContent(json.getString("content"));
        tempOrder.setAddress(json.getString("address"));
        tempOrder.setProvinceCode(json.getString("provinceCode"));
        tempOrder.setCityCode(json.getString("cityCode"));
        tempOrder.setDistrictCode(json.getString("districtCode"));
        tempOrder.setLng(json.getString("lng"));
        tempOrder.setLat(json.getString("lat"));
        tempOrder.setSignIn(json.getBooleanValue("signIn"));
        tempOrder.setAddressDetail(json.getString("addressDetail"));
        tempOrder.setEmergency(Enums.getEnum(EmergencyStateEnum.class, json.getJSONObject("emergency").getString("id")));
        tempOrder.setDoorToDoor(Enums.getEnum(DoorToDoorEnum.class, json.getJSONObject("doorToDoor").getString("id")));
        tempOrder.setWorkOrderState(Enums.getEnum(WorkOrderStateEnum.class, json.getJSONObject("workOrderState").getString("id")));
        tempOrder.setDoorToDoorStartTime(json.getString("doorToDoorStartTime"));
        tempOrder.setDoorToDoorEndTime(json.getString("doorToDoorEndTime"));
        tempOrder.setHandlePositionTitle(json.getString("handlePositionTitle"));
        tempOrder.setAvatar(json.getString("avatar"));

        if (Objects.nonNull(json.getJSONArray("imgIds"))){
            tempOrder.setImgIds(JSONObject.parseArray(json.getJSONArray("imgIds").toString(), String.class));
        }
        if (Objects.nonNull(json.getJSONArray("handleEmployeeNo"))){
            tempOrder.setHandleEmployeeNo(JSONObject.parseArray(json.getJSONArray("handleEmployeeNo").toString(), String.class));
        }
        if (Objects.nonNull(json.getJSONArray("handleEmployeeName"))){
            tempOrder.setHandleEmployeeName(JSONObject.parseArray(json.getJSONArray("handleEmployeeName").toString(), String.class));
        }
        if (Objects.nonNull(json.getJSONArray("handleDepartName"))){
            tempOrder.setHandleDepartName(JSONObject.parseArray(json.getJSONArray("handleDepartName").toString(), String.class));
        }
        if (Objects.nonNull(json.getJSONArray("noticeEmployeeNo"))){
            tempOrder.setNoticeEmployeeNo(JSONObject.parseArray(json.getJSONArray("noticeEmployeeNo").toString(), String.class));
        }
        if (Objects.nonNull(json.getJSONArray("noticeEmployeeName"))){
            tempOrder.setNoticeEmployeeName(JSONObject.parseArray(json.getJSONArray("noticeEmployeeName").toString(), String.class));
        }


        Set<String> set = new HashSet<>();
        Set<String> authorityUserSet = new HashSet<>();
        if (Objects.nonEmpty(tempOrder.getHandleEmployeeNo())){
            set.addAll(tempOrder.getHandleEmployeeNo());
            authorityUserSet.addAll(tempOrder.getHandleEmployeeNo());
        }
        if (Objects.nonEmpty(tempOrder.getNoticeEmployeeNo())){
            authorityUserSet.addAll(tempOrder.getNoticeEmployeeNo());
        }
        authorityUserSet.add(tempOrder.getCreateUserNo());
        tempOrder.setSubmitToMeNo(new ArrayList<>(set));
        tempOrder.setAuthorityUserList(new ArrayList<>(authorityUserSet));

        // tempOrder.setSubmitToMeNo(tempOrder.getHandleEmployeeNo());
        // tempOrder.setSubmitToMeName(tempOrder.getHandleEmployeeName());

        if (Objects.nonEmpty(tempOrder.getTwoClassifyName())) {
            tempOrder.setName(tempOrder.getTwoClassifyName());
        } else {
            tempOrder.setName(tempOrder.getOneClassifyName());
        }
    }

    private void initWorkOrder(WorkOrderManage tempOrder) {
        tempOrder.setId(IDGenerate.nextId());
        tempOrder.setCreateTime(TimeUtil.timestamp());
        tempOrder.setUpdateTime(TimeUtil.timestamp());
        tempOrder.setWorkOrderState(WorkOrderStateEnum.ING);
        tempOrder.setFinishTime(null);
        tempOrder.setUserAppraisal(false);
        tempOrder.setRecordId(null);
    }

    private void setHandleDepart(WorkOrderManage order) {
        Set<String> departSet = new HashSet<>();
        for (int i = 0; i < order.getHandleEmployeeNo().size(); i++) {
            JSONObject employeeJson = getEmployeeById(order.getHandleEmployeeNo().get(i));
            if (Objects.nonNull(employeeJson)) {
                JSONArray depart = employeeJson.getJSONArray("departmentName");
                if (Objects.nonEmpty(depart)){
                    departSet.addAll(JSONArray.parseArray(depart.toJSONString(), String.class));
                }
            }
        }
        order.setHandleDepartName(new ArrayList<>(departSet));
    }

    /**
     * 获取最近节点记录
     * @param id recordId
     * @return
     */
    private WorkOrderManageRecord getNodeRecord(String id) {
        WorkOrderManageRecord record = Pool.get(WorkOrderManageRecord.class, id);
        if (record.isNode() || Objects.isEmpty(record.getParentRecordId())) {
            return record;
        }

        return getNodeRecord(record.getParentRecordId());
    }

    /**
     * 获取上一节点记录
     * @param recordId
     * @return
     */
    private WorkOrderManageRecord getParentNodeRecord(String recordId) {
        WorkOrderManageRecord record = Pool.get(WorkOrderManageRecord.class, recordId);
        if (Objects.isEmpty(record.getParentRecordId())) {
            return record;
        }

        WorkOrderManageRecord parentRecord = Pool.get(WorkOrderManageRecord.class, record.getParentRecordId());
        if (Objects.isEmpty(parentRecord.getParentRecordId())) {
            return parentRecord;
        }

        return getNodeRecord(record.getParentRecordId());
    }

    private JSONObject buildHandleUserJson(WorkOrderManage order, String handleUserNo, String handleUserName) {
        JSONObject jsonObject = createNextEmployee(order);
        jsonObject.put("handleUserNo", handleUserNo);
        jsonObject.put("handleUserName", handleUserName);
        return jsonObject;
    }

    private String insertRecord(JSONObject json, WorkOrderManage order,WorkOrderHandleStateEnum handleState, boolean resetLastCreateTime, boolean userCreate) {
        WorkOrderManageRecord record = Pool.newInstance(WorkOrderManageRecord.class);
        record.setWorkOrderId(order.getId());
        record.setParentRecordId(order.getRecordId());
        record.setHandleState(handleState);
        record.setName(order.getName());
        record.setRemark(json.getString("remark"));
        record.setAddress(json.getString("address"));
        record.setLng(json.getString("lng"));
        record.setLat(json.getString("lat"));
        record.setNode(true);
        record.setUserCreate(userCreate);
        record.setNextEmployeeNo(json.getString("nextUserNo"));
        record.setNextEmployeeName(json.getString("nextUserName"));
        record.setHandlePositionTitle(json.getString("handlePositionTitle"));
        record.setAvatar(json.getString("avatar"));
        if (Objects.nonEmpty(json.getJSONArray("imgIds"))){
            record.setImgIds(JSONObject.parseArray(json.getJSONArray("imgIds").toString(), String.class));
        }
        record.setHandleEmployeeNo(json.getString("handleUserNo"));
        record.setHandleEmployeeName(json.getString("handleUserName"));

        record.setLastCreateTime(TimeUtil.timestamp());
        if (Objects.nonEmpty(order.getRecordId())) {
            WorkOrderManageRecord parentRecord = Pool.get(WorkOrderManageRecord.class, order.getRecordId());
            record.setLastCreateTime(parentRecord.getCreateTime());

            if (resetLastCreateTime) {
                record.setLastCreateTime(parentRecord.getLastCreateTime());
                record.setNode(false);
            }
        }

        jdbcSession.insert(record);

        return record.getId();
    }

    public Object reminders(String id){
        WorkOrderManageReminders reminders = Pool.get(WorkOrderManageReminders.class, id);
        if (Objects.isNull(reminders)) {
            reminders = Pool.newInstance(WorkOrderManageReminders.class, id);
            jdbcSession.insert(reminders);

            WorkOrderManage order = Pool.get(WorkOrderManage.class, id);
            List<String> handleEmployee = order.getHandleEmployeeNo();
            if (Objects.nonEmpty(handleEmployee)) {
                handleEmployee.forEach(e -> notifyEmployee("3", e, order.getCreateUserNo(), order.getCreateUserName(), order.getName(), order.getId()));
            }
            return Result.success();
        }

        if (reminders.getUpdateTime().toLocalDateTime().plusHours(4L).isBefore(LocalDateTime.now())){
            jdbcSession.updateById(reminders);
            return Result.success();
        } else {
            return Result.error(0, "您好，需要4小时后才能再次催办");
        }
    }

    public Object signInList(JSONObject jsonObject) {
        return Result.success(jdbcSession.findPage(WorkOrderManageRecord.class)
                                                          .eq(jsonObject, "workOrderId")
                                                          .eq("handleState", WorkOrderHandleStateEnum.SIGN_IN)
                                                          .page(jsonObject)
                                                          .exe());
    }

    public Object signInDetail(String id) {
        return Result.success(Pool.get(WorkOrderManageRecord.class, id));
    }

    /**
     * <p>员工端提醒消息</p>
     * <p>{createUserName}{typeId}一个《{title}》指定由您处理/给您</p>
     * @param typeId 消息类型：1发起，2抄送，3催办
     * @param uuid 接收员工ID
     * @param createUserNo 工单创建人ID
     * @param createUserName 工单创建人
     * @param title 工单名称
     * @return
     */
    public void notifyEmployee(String typeId, String uuid, String createUserNo, String createUserName, String title, String msgId){
        try {
            doveClient.post("/crm/message/service/notify/employee", (http) -> {
                JSONObject type = new JSONObject();
                type.put("id", typeId);

                JSONObject body = new JSONObject();
                body.put("uuid", uuid);
                body.put("createUserNo", createUserNo);
                body.put("createUserName", createUserName);
                body.put("type", type);
                body.put("title", title);
                body.put("msgId", msgId);

                http.setBody(body.toString());
            });
        } catch (Exception e){
            e.printStackTrace();
        }
    }


}
